#include "heaptimer.h"
#include <assert.h>

HeapTimer::HeapTimer() {
    m_heap.reserve(64); // 初始化堆大小,更改capacity
}

HeapTimer::~HeapTimer() {
    m_heap.clear();
    m_ref.clear();
}

bool HeapTimer::SiftDown(size_t index, size_t n) {
    assert(index >= 0 && index < m_heap.size());
    assert(n >= 0 && n < m_heap.size());

    size_t i = index;
    size_t j = i * 2 + 1;
    while(j < n) {
        // 找到左右节点较小的值
        if (j + 1 < n && m_heap[j + 1] < m_heap[j]) {
            ++j; 
        }
        // 满足性质，跳出循环
        if (m_heap[i] < m_heap[j]) {
            break;
        }
        SwapNode(i, j); // 交换节点与左右较小子节点
        i = j;
        j = i * 2 + 1;
    }
    return i > index;
}

void HeapTimer::SiftUp(size_t index) {
    assert(index >= 0 && index < m_heap.size());
    size_t i = index;
    size_t j = (i - 1) / 2;
    while(j >= 0) {
        if (m_heap[j] < m_heap[i]) {
            break;
        }
        SwapNode(i, j);
        i = j;
        j = (i - 1) / 2;
    }
}

void HeapTimer::SwapNode(size_t i, size_t j) {
    assert(i >= 0 && i < m_heap.size());
    assert(j >= 0 && j < m_heap.size());
    std::swap(m_heap[i], m_heap[j]);
    m_ref[m_heap[i].id] = j;
    m_ref[m_heap[j].id] = i;
}

void HeapTimer::Adjust(int id, int timeout) {
    assert(!m_heap.empty() && m_ref.count(id) > 0);
    m_heap[id].expires = Clock::now() + MS(timeout);
    SiftDown(m_ref[id], m_heap.size());
}

void HeapTimer::Delete(size_t index) {
    assert(!m_heap.empty() && index >= 0 && index < m_heap.size());
    size_t i = index;
    size_t n = m_heap.size() - 1;
    assert(i <= n);
    // 和队尾元素交换并调整堆,调整堆时以size-1为范围
    if (i < n) {
        SwapNode(i, n);
        if (SiftDown(i, n)) {
            SiftUp(i);
        }
    }
    // 删除尾部节点
    m_ref.erase(m_heap.back().id);
    m_heap.pop_back();
}

void HeapTimer::Dowork(int id) {
    if (!m_heap.empty() && m_ref.count(id) != 0) {
        return;
    }
    size_t i = m_ref[id];
    TimerNode node = m_heap[i];
    node.cb();
    Delete(i);
}

void HeapTimer::Tick() {
    if (m_heap.empty()) {
        return;
    }

    while(!m_heap.empty()) {
        TimerNode node = m_heap.front();
        // 未超时
        if (std::chrono::duration_cast<MS>(node.expires - Clock::now()).count() > 0) {
            break;
        }
        node.cb();
        pop();
    }
}

void HeapTimer::pop() {
    assert(!m_heap.empty());
    Delete(0);
}

int HeapTimer::GetNextTick() {
    Tick();
    int ret = -1;
    if (!m_heap.empty()) {
        ret = std::chrono::duration_cast<MS>(m_heap.front().expires - Clock::now()).count();
        if (ret < 0) {
            ret = 0;
        }
    }
    return ret;
}

void HeapTimer::Add(int id, int timeout, const TimeoutCallBack& cb) {
    assert(id >= 0);
    size_t i;
    // 新节点，堆尾插入，向上调整
    if (m_ref.count(id) == 0) {
        i = m_heap.size();
        m_ref[id] = i;
        m_heap.push_back({id, Clock::now() + MS(timeout), cb});
        SiftUp(i);
    } else {
        i = m_ref[id];
        m_heap[i].expires = Clock::now() + MS(timeout);
        m_heap[i].cb = cb;
        if (!SiftDown(i, m_heap.size())) {
            SiftUp(i);
        }
    }
}